package com.qqtech.qquan.sms.service;

import java.sql.Timestamp;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.ws.rs.GET;
import javax.ws.rs.Path;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.stereotype.Service;

import com.qqtech.core.common.enums.RespEnum;
import com.qqtech.core.common.enums.YesNoEnum;
import com.qqtech.core.common.util.JsonUtil;
import com.qqtech.core.common.util.StringUtil;
import com.qqtech.core.common.util.TimeUtil;
import com.qqtech.core.frame.dao.BaseDao;
import com.qqtech.core.frame.model.PageKit;
import com.qqtech.core.frame.model.PageOrder;
import com.qqtech.core.frame.model.Result;
import com.qqtech.core.frame.service.BaseServiceImpl;
import com.qqtech.qquan.sms.cache.SmsSysParamCache;
import com.qqtech.qquan.sms.dao.SmsBaseDao;
import com.qqtech.qquan.sms.enums.SmsConst;
import com.qqtech.qquan.sms.enums.SmsTemplateTypeDictEnum;
import com.qqtech.qquan.sms.model.SmsBase;
import com.qqtech.qquan.sms.model.SmsProvider;
import com.qqtech.qquan.sms.model.SmsProviderTemplate;
import com.qqtech.qquan.sms.model.SmsTemplate;

@Service
public class SmsBaseServiceImpl extends BaseServiceImpl<SmsBase>implements SmsBaseService {
	public static final Logger log = LoggerFactory.getLogger(SmsBaseServiceImpl.class);
	@Resource
	private SmsProviderService smsProviderService;
	@Resource
	private SmsTemplateService smsTemplateService;
	@Resource
	private SmsProviderTemplateService smsProviderTemplateService;
	@Resource
	private SmsSysParamCache smsSysParamCache;
	@Resource
	private SmsApiService smsApiAliService;

	@Resource
	private SmsBaseDao smsBaseDao;

	@Override
	protected BaseDao<SmsBase> getBaseDao() {
		return smsBaseDao;
	}

	@Override
	public Integer getRateInterval() {
		return smsSysParamCache.getInt(SmsConst.PARAMKEY_SMS_LIMIT_RATE_INTERVAL, 120);
	}

	@Override
	public Result send(String mobile, Integer templateId, Map<String, String> params) {
		try {
			// 基本验证和判断
			if (StringUtil.isBlank(mobile)) {
				log.error("接收手机号码不能为空,mobile={}", mobile);
				return new Result(RespEnum.EXCEPTION, "接收手机号码不能为空,mobile=" + mobile);
				// throw new SmsException("接收手机号码不能为空,mobile=" + mobile);
			}
			if (mobile.indexOf(";") >= 0) {
				if (YesNoEnum.YES.getCode() != smsSysParamCache.getInt(SmsConst.PARAMKEY_SMS_MASS_ENABLE)) {
					log.error("没有开启短信群发功能");
					return new Result(RespEnum.EXCEPTION, "没有开启短信群发功能");
					// throw new SmsException("没有开启短信群发功能");
				}
			}
			List<SmsProvider> spList = smsProviderService.queryAllProviderByPriorityAsc();
			if (spList == null || spList.size() == 0) {
				log.error("没有有效的短信服务商");
				return new Result(RespEnum.EXCEPTION, "没有有效的短信服务商");
				// throw new SmsException("没有有效的短信服务商");
			}
			SmsTemplate smsTemplate = smsTemplateService.getById(templateId);
			if (smsTemplate == null) {
				log.error("还没设置短信模板,templateId={}", templateId);
				return new Result(RespEnum.EXCEPTION, "还没设置短信模板,templateId=" + templateId);
				// throw new SmsException("还没设置短信模板,templateId=" + templateId);
			}
			SmsProviderTemplate smsProviderTemplate = new SmsProviderTemplate();
			smsProviderTemplate.setTemplateId(templateId);
			List<SmsProviderTemplate> listSpt = smsProviderTemplateService.queryList(smsProviderTemplate);
			if (listSpt == null || listSpt.size() == 0) {
				log.error("没有有效的短信模板,templateId={}", templateId);
				return new Result(RespEnum.EXCEPTION, "没有有效的短信模板,templateId=" + templateId);
				// throw new SmsException("没有有效的短信模板,templateId=" + templateId);
			}
			if (mobile.indexOf(";") >= 0 && SmsTemplateTypeDictEnum.VERIFY.getCode() == smsTemplate.getType()) {
				log.error("不允许群发验证码短信");
				return new Result(RespEnum.EXCEPTION, "不允许群发验证码短信");
				// throw new SmsException("不允许群发验证码短信");
			}
			// 针对验证码短信的频率限制
			if (SmsTemplateTypeDictEnum.VERIFY.getCode() == smsTemplate.getType()) {
				SmsBase smsBase = new SmsBase();
				smsBase.setPhone(mobile);
				smsBase.setType(SmsTemplateTypeDictEnum.VERIFY.getCode());
				int rateSize = smsSysParamCache.getInt(SmsConst.PARAMKEY_SMS_LIMIT_RATE_ALLTIMES, 5);
				PageKit page = new PageKit(1, rateSize, new PageOrder(Direction.DESC, "id"));
				List<SmsBase> listSmsBase = smsBaseDao.queryList(smsBase, page);
				if (listSmsBase != null && listSmsBase.size() > 0) {
					Timestamp now = TimeUtil.now();
					// 判断是否超过规定时间的总数
					if (listSmsBase.size() == rateSize) {
						smsBase = listSmsBase.get(rateSize - 1);
						int rateMins = smsSysParamCache.getInt(SmsConst.PARAMKEY_SMS_LIMIT_RATE_ALLMINS, 720);
						if (rateMins > TimeUtil.minsOfTwo(smsBase.getNewAt(), now)) {
							int hours = rateMins / 60;
							log.error("{}小时内只能发送{}条短信", hours, rateSize);
							return new Result(RespEnum.EXCEPTION, hours + "小时内只能发送" + rateSize + "条短信");
							// throw new SmsException(hours + "小时内只能发送" +
							// rateSize +
							// "条短信");
						}
					}
					// 判断频率是否过快
					smsBase = listSmsBase.get(0);
					int rateInterval = smsSysParamCache.getInt(SmsConst.PARAMKEY_SMS_LIMIT_RATE_INTERVAL, 120);
					int leftSeconds = TimeUtil.secondsOfTwo(smsBase.getNewAt(), now);
					if (rateInterval > leftSeconds) {
						log.error("请在{}秒后再发送短信", rateInterval - leftSeconds);
						return new Result(RespEnum.EXCEPTION, "请在" + (rateInterval - leftSeconds) + "秒后再发送短信");
						// throw new SmsException("请在" + (rateInterval -
						// leftSeconds) + "秒后再发送短信");
					}
				}
			}
			// 保存请求短信发送记录
			SmsBase smsBase = new SmsBase();
			smsBase.setPhone(mobile);
			smsBase.setTemplate(smsTemplate.getContent());
			smsBase.setTemplateParam(JsonUtil.toJson(params));
			smsBase.setSignName(smsSysParamCache.get(SmsConst.PARAMKEY_SMS_DEFAULT_SIGNATURE));
			smsBase.setReturnStatus(YesNoEnum.NO.getCode());
			smsBase.setReturnMsg("");
			smsBase.setSpName("");
			smsBase.setExtend("");
			smsBase.setType(smsTemplate.getType());
			smsBase.setSptId(0);
			smsBase.setTemplateId(templateId);
			smsBaseDao.insert(smsBase);

			String useStatus = smsSysParamCache.get(SmsConst.PARAMKEY_SMS_USE_STATUS);
			if (!("" + YesNoEnum.YES.getCode()).equals(useStatus)) {
				return new Result(RespEnum.EXCEPTION, "短信开关已关闭");
			}

			// 按优先度选择可以发送短信的厂商
			Hashtable<Integer, SmsProviderTemplate> spMap = new Hashtable<Integer, SmsProviderTemplate>();
			for (SmsProviderTemplate spt : listSpt) {
				spMap.put(spt.getProviderId(), spt);
			}
			boolean isFonud = false;
			for (SmsProvider sp : spList) {
				if (spMap.get(sp.getId()) != null) {
					smsProviderTemplate = spMap.get(sp.getId());
					Result sendRt = null;
					if (sp.getId().equals(smsSysParamCache.getInt(SmsConst.PARAMKEY_SMS_PROVIDER_ID_ALIDAYU))) {
						sendRt = smsApiAliService.doSend(mobile, smsProviderTemplate.getSpTemplateId(), params);
						isFonud = true;
					}
					if (sendRt != null && RespEnum.OK.getCode() == sendRt.getCode()) {
						smsBase.setReturnStatus(YesNoEnum.YES.getCode());
						smsBase.setReturnMsg(sendRt.getMsg());
						smsBase.setSptId(smsProviderTemplate.getId());
						smsBase.setSpName(sp.getName());
						smsBaseDao.updateById(smsBase);
						return sendRt;
					}
				}
			}
			if (isFonud == false) {
				log.error("找不到提供该模板({})服务的短信厂商", templateId);
				return new Result(RespEnum.EXCEPTION, "找不到提供该模板(" + templateId + ")服务的短信厂商");
				// throw new SmsException("找不到提供该模板(" + templateId +
				// ")服务的短信厂商");
			}
			return new Result(RespEnum.EXCEPTION, "短信发送失败");
		} catch (Exception e) {
			e.printStackTrace();
			log.error("短信发生异常-{}", e.getMessage());
			return new Result(RespEnum.EXCEPTION, "短信发生异常");
		}
	}

	/**
	 * rest接口可以这样访问--http://ip:port/api/sms/base/1
	 */
	@GET
	@Path("/do")
	@Override
	public Result testSmsBase() {
		Map<String, String> params = new HashMap<String, String>();
		params.put("code", "123666");
		params.put("product", "vakool");
		return this.send("13332984398", 1001, params);
	}
}